home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Linux Cubed Series 7: Sunsite
/
Linux Cubed Series 7 - Sunsite Vol 1.iso
/
system
/
admin
/
pwdutils.00
/
pwdutils
/
pwdutils-1.00
/
vipw.c
< prev
next >
Wrap
C/C++ Source or Header
|
1996-05-08
|
4KB
|
187 lines
/*
** Copyright 1996 Thorsten Kukuk <kukuk@uni-paderborn.de>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <pwd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <waitflags.h>
#include <sys/wait.h>
#include <getopt.h>
#include "pwdutils.h"
#include "version.h"
static struct option vipw_options[] = {
{ "version", no_argument, 0, 'v' },
{ NULL, no_argument, 0, '0' },
};
static char *vipw_str = "v";
void pwd_exit(int code)
{
unlink(PWD_TEMP);
ulckpwdf();
exit(code);
}
void create_tmpfile()
{
int nr, nw, off, from, to;
char buf[8*1024];
from = open(PWD_PATH, O_RDONLY, 0);
if (from < 0)
{
fprintf(stderr, "vipw: %s: %s\n", PWD_PATH, strerror(errno));
pwd_exit(1);
}
if ((to = open(PWD_TEMP, O_WRONLY|O_CREAT, 0644)) == -1)
{
fprintf(stderr,"vipw: %s: %s\n", PWD_TEMP, strerror(errno));
pwd_exit(1);
}
while ((nr = read(from, buf, sizeof(buf))) > 0)
for (off = 0; off < nr; nr -= nw, off += nw)
if ((nw = write(to, buf + off, nr)) < 0)
pwd_error("Error by copying " PWD_PATH " to " PWD_TEMP, PWD_PATH);
if (nr < 0)
pwd_error("Error by copying " PWD_PATH " to " PWD_TEMP, PWD_PATH);
}
void call_editor()
{
static char *editor, *prgname, *arg;
int pid, sock;
if ((editor = getenv("EDITOR"))==NULL)
editor = VI_PATH;
if ((prgname = strrchr(strtok(editor," \t"), '/')) != NULL)
prgname++;
else
prgname = editor;
/* I need the parameter in the EDITOR environment variable.
** This isn't a security risc, since only root is allowed
** to run this program and edit the passwd file.
** VIPW SHOULD NEVER RUN SETUID ROOT !
*/
arg = strtok(NULL,"\n");
switch(pid=fork())
{
case -1:
perror("Cannot fork");
exit(-1);
break;
case 0:
if(arg == NULL)
execlp(editor, prgname, PWD_TEMP, NULL);
else
execlp(editor, prgname, arg, PWD_TEMP, NULL);
_exit(1);
break;
default:
while(1)
{
pid = waitpid(pid,&sock, WUNTRACED);
if(WIFSTOPPED(sock))
{
kill(getpid(),SIGSTOP);
kill(pid, SIGCONT);
}
else
break;
}
break;
}
}
int main(int argc, char *argv[])
{
struct stat begin, end;
int c, index = 0;
while((c = getopt_long(argc, argv, vipw_str, vipw_options, &index))!= EOF)
{
switch(c)
{
case 'v':
printf("pwdutils %s\n", version);
exit (0);
break;
default:
break;
}
}
argc-=optind;
argv+=optind;
if(getuid() != 0)
{
fprintf(stderr,"vipw: Only root could edit %s !\n", PWD_PATH);
exit(1);
}
pwd_init();
if(lckpwdf() != 0)
{
fprintf(stderr,"vipw: Can't lock /etc/passwd! Try again later.\n");
exit(1);
}
create_tmpfile();
if (stat(PWD_TEMP, &begin))
pwd_error(strerror(errno), PWD_PATH);
call_editor();
if (stat(PWD_TEMP, &end))
pwd_error(strerror(errno), PWD_PATH);
if (begin.st_mtime == end.st_mtime)
{
fprintf(stderr, "vipw: no changes made, %s unchanged\n",PWD_PATH);
}
else
{
unlink(PWD_PATH);
if (rename(PWD_TEMP, PWD_PATH) == -1)
{
fprintf(stderr, "vipw: can't unlock %s: %s (your changes are still in %s)\n",
PWD_PATH, strerror(errno), PWD_TEMP);
exit(1);
}
unlink(PWD_TEMP);
}
pwd_exit(0);
}